#include "bull_hal_ota_flash.h"

// #include "aiot_ota_api.h"



static const char* OTA_TAG = "hal_ota";


/**
 * @brief 擦除上个分区
 * 
 * @return OPERATE_RET 
 */
OPERATE_RET bull_hal_ota_ease_last_boot( void )
{
    int ret = 0;
    ret = esp_ota_erase_last_boot_app_partition();
    ESP_LOGI( OTA_TAG,"esp_ota_erase_last_boot_app_partition:%d",ret);
    return ret;
}


/**
 * @brief 将接收到的数据写入到flash里面
 * 
 * @param data 接收的数据
 * @param len 接收数据长度
 */
OPERATE_RET bull_hal_ota_write_data( uint32_t update_handle, uint8_t *data, uint16_t len )
{
     int ret = OPRT_OK;

    //写flash
    ret = esp_ota_write(update_handle, (const void *)data, len);
    if (ret != OPRT_OK) {
        // BULL_HEXDUMP("err",16,data,len);
        ESP_LOGE( OTA_TAG,"esp_ota_write failed!");
    }

    return ret;
}

/**
 * @brief 接收完OTA数据准备重启
 * 
 * @param update_handle 
 * @param update_partition 
 * @return OPERATE_RET 
 */
OPERATE_RET bull_hal_ota_write_end(uint32_t update_handle,const esp_partition_t *update_partition)
{
    int ret = OPRT_OK;

    //OTA写结束
    if (esp_ota_end(update_handle) != OPRT_OK) {
        ESP_LOGE( OTA_TAG,"esp_ota_end failed!");
    }

    //升级完成更新OTA data区数据，重启时根据OTA data区数据到Flash分区加载执行目标（新）固件
    ret = esp_ota_set_boot_partition((esp_partition_t *)update_partition);
    if (ret != ESP_OK) {
        ESP_LOGE( OTA_TAG,"esp_ota_set_boot_partition failed! err=0x%x", ret);
        return ret;
    }
    ESP_LOGI( OTA_TAG,"Prepare to restart system!");
    // esp_restart();

    return ret;
}


/**
 * @brief ota开始下载数据前，检查是否正常
 * 
 * @return true 
 * @return false 
 */
bool bull_hal_ota_start_check(void)
{
    //获取OTA app存放的位置
    const esp_partition_t *configured = esp_ota_get_boot_partition();

    //获取当前系统执行的固件所在的Flash分区
    const esp_partition_t *running = esp_ota_get_running_partition();


    if (configured != running) {
        // ESP_LOGW( OTA_TAG,"Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x", configured->address, running->address);
        return false;
    }

    // ESP_LOGI( OTA_TAG,"Running partition type %d subtype %d (offset 0x%08x)",running->type, running->subtype, running->address);

    return true;
}


/**
 * @brief 获取将要升级的区域
 * 
 * @return void* 
 */
const void* bull_hal_ota_get_update_pariton(void)
{   

    const esp_partition_t * update_partition =NULL;

    //获取当前系统下一个（紧邻当前使用的OTA_X分区）可用于烧录升级固件的Flash分区
    update_partition = esp_ota_get_next_update_partition(NULL);
    if(update_partition == NULL){
        ESP_LOGE( OTA_TAG,"error update_partition");
    }

    return update_partition;
}




/**
 * @brief 开始ota 升级
 * 
 * @param update_partition 
 * @param update_handle 返回当前升级的句柄
 * @return int 
 */
OPERATE_RET bull_hal_ota_begin(void* update_partition,OUT uint32_t *update_handle)
{
    int ret = OPRT_OK;

    //OTA写开始
    ret = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, update_handle);
    if (ret != ESP_OK) {
        ESP_LOGE( OTA_TAG,"esp_ota_begin failed, error=%d", ret);
        return ret;
    }
    ESP_LOGI( OTA_TAG, "esp_ota_begin succeeded");

    return ret;
}
